<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head>
  <link href="//gmpg.org/xfn/11" rel="profile">
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="generator" content="Hugo 0.68.3" />

  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>python三程 &middot; 我的博客</title>

  
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/print.css" media="print">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/poole.css">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/syntax.css">
  <link type="text/css" rel="stylesheet" href="/my_technology_blog/css/hyde.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Abril+Fatface|PT+Sans:400,400i,700">


  
  <link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png">
  <link rel="shortcut icon" href="/favicon.png">

  
  
</head>

  <body class="theme-base-0b ">
  <aside class="sidebar">
  <div class="container sidebar-sticky">
    <div class="sidebar-about">
      <a href="/my_technology_blog/"><h1>我的博客</h1></a>
      <p class="lead">
       杨博的博客 
      </p>
    </div>

    <nav>
      <ul class="sidebar-nav">
        <li><a href="/my_technology_blog/">Home</a> </li>
        
      </ul>
    </nav>

    <p>&copy; 2021. All rights reserved. </p>
  </div>
</aside>

    <main class="content container">
    <div class="post">
  <h1>python三程</h1>
  <time datetime=2020-06-26T13:05:56&#43;0800 class="post-date">Fri, Jun 26, 2020</time>
  <h2 id="进程">进程</h2>
<p><strong>1.</strong> <strong>进程定义</strong></p>
<ol>
<li>
<p>进程是资源分配最小单位</p>
</li>
<li>
<p>当一个可执行程序被系统执行（分配内存等资源）就变成了一个进程</p>
</li>
</ol>
<p><strong>进程定义拓展回答内容</strong></p>
<ol>
<li>
<p>程序并不能单独运行，只有将程序装载到内存中，系统为它分配资源才能运行，这种执行的程序就称之为进程</p>
</li>
<li>
<p>程序和进程的区别就在于：程序是指令的集合，它是进程运行的静态描述文本；进程是程序的一次执行活动，属于动态概念</p>
</li>
<li>
<p>在多道编程中，我们允许多个程序同时加载到内存中，在操作系统的调度下，可以实现并发地执行。</p>
</li>
<li>
<p>进程的出现让每个用户感觉到自己独享CPU，因此，进程就是为了在CPU上实现多道编程而提出的。</p>
</li>
<li>
<p>进程之间有自己独立的内存，各进程之间不能相互访问</p>
</li>
<li>
<p>创建一个新线程很简单，创建新进程需要对父进程进行复制</p>
</li>
</ol>
<p><strong>多道编程概念</strong></p>
<p>多道编程： 在计算机内存中同时存放几道相互独立的程序，他们共享系统资源，相互穿插运行</p>
<p>单道编程： 计算机内存中只允许一个的程序运行</p>
<p><strong>2.</strong> <strong>有了进程为什么还要线程？</strong></p>
<ol>
<li>
<p>进程优点：</p>
<p>提供了多道编程，让我们感觉我们每个人都拥有自己的CPU和其他资源，可以提高计算机的利用率</p>
</li>
<li>
<p>进程的两个重要缺点</p>
<p>a. 第一点：进程只能在一个时间干一件事，如果想同时干两件事或多件事，进程就无能为力了。</p>
<p>b. 第二点：进程在执行的过程中如果阻塞，即使进程中有些工作不依赖于输入的数据，也将无法执行（例如等待输入，整个进程就会挂起）。</p>
<p>c. 例如，我们在使用qq聊天， qq做为一个独立进程如果同一时间只能干一件事，那他如何实现在同一时刻 即能监听键盘输入、又能监听其它人给你发的消息</p>
<p>d. 你会说，操作系统不是有分时么？分时是指在不同进程间的分时呀</p>
<p>e. 即操作系统处理一会你的qq任务，又切换到word文档任务上了，每个cpu时间片分给你的qq程序时，你的qq还是只能同时干一件事呀</p>
</li>
</ol>
<p><strong>3.</strong> <strong>进程间互相访问数据的四种方法</strong></p>
<p>**注：**不同进程间内存是不共享的，所以互相之间不能访问对方数据</p>
<p>法1: 利用Queues实现父进程到子进程（或子进程间）的数据传递</p>
<p>法2: 使用管道pipe实现两个进程间数据传递</p>
<p>法3: Managers实现很多进程间数据共享</p>
<p>法4：借助redis中间件进行数据共享</p>
<p><strong>4.</strong> <strong>进程池</strong></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">from</span>  multiprocessing <span style="color:#f92672">import</span> Process,Pool
<span style="color:#f92672">import</span> time<span style="color:#f92672">,</span>os
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">foo</span>(i):
    time<span style="color:#f92672">.</span>sleep(<span style="color:#ae81ff">2</span>)
    <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#34;in the process&#34;</span>,os<span style="color:#f92672">.</span>getpid()) <span style="color:#75715e">#打印子进程的pid</span>
<span style="color:#66d9ef">return</span> i<span style="color:#f92672">+</span><span style="color:#ae81ff">100</span>
 
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">call</span>(arg):
<span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#39;--&gt;exec done:&#39;</span>,arg,os<span style="color:#f92672">.</span>getpid())
 
<span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74">&#39;__main__&#39;</span>:
    pool <span style="color:#f92672">=</span> Pool(<span style="color:#ae81ff">3</span>)                      <span style="color:#75715e">#进程池最多允许5个进程放入进程池</span>
    <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#34;主进程pid：&#34;</span>,os<span style="color:#f92672">.</span>getpid())     <span style="color:#75715e">#打印父进程的pid</span>
    <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">10</span>):
       <span style="color:#75715e">#用法1 callback作用是指定只有当Foo运行结束后就执行callback调用的函数,父进程调用的callback函数</span>
        pool<span style="color:#f92672">.</span>apply_async(func<span style="color:#f92672">=</span>foo, args<span style="color:#f92672">=</span>(i,),callback<span style="color:#f92672">=</span>call)
        <span style="color:#75715e">#用法2 串行 启动进程不在用Process而是直接用pool.apply()</span>
        <span style="color:#75715e"># pool.apply(func=foo, args=(i,))</span>
    <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#39;end&#39;</span>)
    pool<span style="color:#f92672">.</span>close()    <span style="color:#75715e">#关闭pool</span>
    pool<span style="color:#f92672">.</span>join()     <span style="color:#75715e">#进程池中进程执行完毕后再关闭，如果注释，那么程序直接关闭。</span>
</code></pre></div><p><strong>5.</strong> <strong>进程和程序的区别</strong></p>
<ol>
<li>
<p>程序只是一个普通文件，是一个机器代码指令和数据的集合，所以，程序是一个静态的实体</p>
</li>
<li>
<p>而进程是程序运行在数据集上的动态过程，进程是一个动态实体，它应创建而产生，应调度执行因等待资源或事件而被处于等待状态，因完成任务而被撤消</p>
</li>
<li>
<p>进程是系统进行资源分配和调度的一个独立单位</p>
</li>
<li>
<p>一个程序对应多个进程，一个进程为多个程序服务（两者之间是多对多的关系）</p>
</li>
<li>
<p>一个程序执行在不同的数据集上就成为不同的进程，可以用进程控制块来唯一地标识每个进程</p>
</li>
</ol>
<h2 id="线程">线程</h2>
<ol>
<li>
<p>线程定义</p>
<p>线程是操作系统调度的最小单位</p>
<p>它被包含在进程之中，是进程中的实际运作单位</p>
<p>进程本身是无法自己执行的，要操作cpu，必须创建一个线程，线程是一系列指令的集合</p>
</li>
</ol>
<p><strong>线程定义拓展回答内容</strong></p>
<ol>
<li>
<p>线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中，是进程中的实际运作单位</p>
</li>
<li>
<p>一条线程指的是进程中一个单一顺序的控制流，一个进程中可以并发多个线程，每条线程并行执行不同的任务</p>
</li>
<li>
<p>无论你启多少个线程，你有多少个cpu, Python在执行的时候会淡定的在同一时刻只允许一个线程运行</p>
</li>
<li>
<p>进程本身是无法自己执行的，要操作cpu，必须创建一个线程，线程是一系列指令的集合</p>
</li>
<li>
<p>所有在同一个进程里的线程是共享同一块内存空间的，不同进程间内存空间不同</p>
</li>
<li>
<p>同一个进程中的各线程可以相互访问资源，线程可以操作同进程中的其他线程，但进程仅能操作子进程</p>
</li>
<li>
<p>两个进程想通信，必须要通过一个中间代理</p>
</li>
<li>
<p>对主线程的修改可能回影响其他子线程，对主进程修改不会影响其他进程因为进程间内存相互独立，但是同一进程下的线程共享内存</p>
</li>
</ol>
<p><strong>2.</strong> <strong>进程和线程的区别</strong></p>
<p>​	1、进程包含线程</p>
<p>​	2、线程共享内存空间</p>
<p>​	3、进程内存是独立的（不可互相访问）</p>
<p>​	4、进程可以生成子进程，子进程之间互相不能互相访问（相当于在父级进程克隆两个子进程）</p>
<p>​	5、在一个进程里面线程之间可以交流。两个进程想通信，必须通过一个中间代理来实现</p>
<p>​	6、创建新线程很简单，创建新进程需要对其父进程进行克隆。</p>
<p>​	7、一个线程可以控制或操作同一个进程里面的其它线程。但进程只能操作子进程。</p>
<p>​	8、父进程可以修改不影响子进程，但不能修改。</p>
<p>​	9、线程可以帮助应用程序同时做几件事</p>
<p><strong>3. for</strong> <strong>循环同时启动多个线程</strong></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> threading
<span style="color:#f92672">import</span> time
 
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">sayhi</span>(num): <span style="color:#75715e">#定义每个线程要运行的函数</span>
    <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#34;running on number:</span><span style="color:#e6db74">%s</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">%</span>num)
    time<span style="color:#f92672">.</span>sleep(<span style="color:#ae81ff">3</span>)
<span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">50</span>):
    t <span style="color:#f92672">=</span> threading<span style="color:#f92672">.</span>Thread(target<span style="color:#f92672">=</span>sayhi,args<span style="color:#f92672">=</span>(<span style="color:#e6db74">&#39;t-</span><span style="color:#e6db74">%s</span><span style="color:#e6db74">&#39;</span><span style="color:#f92672">%</span>i,))
    t<span style="color:#f92672">.</span>start()
</code></pre></div><p><strong>4. t.join()</strong> <strong>： 实现所有线程都执行结束后再执行主线程</strong></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> threading
<span style="color:#f92672">import</span> time
start_time <span style="color:#f92672">=</span> time<span style="color:#f92672">.</span>time()
 
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">sayhi</span>(num): <span style="color:#75715e">#定义每个线程要运行的函数</span>
    <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#34;running on number:</span><span style="color:#e6db74">%s</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">%</span>num)
    time<span style="color:#f92672">.</span>sleep(<span style="color:#ae81ff">3</span>)
t_objs <span style="color:#f92672">=</span> []    <span style="color:#75715e">#将进程实例对象存储在这个列表中</span>
<span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">50</span>):
    t <span style="color:#f92672">=</span> threading<span style="color:#f92672">.</span>Thread(target<span style="color:#f92672">=</span>sayhi,args<span style="color:#f92672">=</span>(<span style="color:#e6db74">&#39;t-</span><span style="color:#e6db74">%s</span><span style="color:#e6db74">&#39;</span><span style="color:#f92672">%</span>i,))
    t<span style="color:#f92672">.</span>start()          <span style="color:#75715e">#启动一个线程，程序不会阻塞</span>
    t_objs<span style="color:#f92672">.</span>append(t)
<span style="color:#66d9ef">print</span>(threading<span style="color:#f92672">.</span>active_count())    <span style="color:#75715e">#打印当前活跃进程数量</span>
<span style="color:#66d9ef">for</span> t <span style="color:#f92672">in</span> t_objs: <span style="color:#75715e">#利用for循环等待上面50个进程全部结束</span>
    t<span style="color:#f92672">.</span>join()     <span style="color:#75715e">#阻塞某个程序</span>
<span style="color:#66d9ef">print</span>(threading<span style="color:#f92672">.</span>current_thread())    <span style="color:#75715e">#打印执行这个命令进程</span>
 
<span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#34;----------------all threads has finished.....&#34;</span>)
<span style="color:#66d9ef">print</span>(threading<span style="color:#f92672">.</span>active_count())
<span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#39;cost time:&#39;</span>,time<span style="color:#f92672">.</span>time() <span style="color:#f92672">-</span> start_time)
</code></pre></div><p><strong>5. setDaemon():</strong> <strong>守护线程，主线程退出时，需要子线程随主线程退出</strong></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> threading
<span style="color:#f92672">import</span> time
start_time <span style="color:#f92672">=</span> time<span style="color:#f92672">.</span>time()
 
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">sayhi</span>(num): <span style="color:#75715e">#定义每个线程要运行的函数</span>
    <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#34;running on number:</span><span style="color:#e6db74">%s</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">%</span>num)
    time<span style="color:#f92672">.</span>sleep(<span style="color:#ae81ff">3</span>)
<span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">50</span>):
    t <span style="color:#f92672">=</span> threading<span style="color:#f92672">.</span>Thread(target<span style="color:#f92672">=</span>sayhi,args<span style="color:#f92672">=</span>(<span style="color:#e6db74">&#39;t-</span><span style="color:#e6db74">%s</span><span style="color:#e6db74">&#39;</span><span style="color:#f92672">%</span>i,))
    t<span style="color:#f92672">.</span>setDaemon(True)  <span style="color:#75715e">#把当前线程变成守护线程，必须在t.start()前设置</span>
    t<span style="color:#f92672">.</span>start()          <span style="color:#75715e">#启动一个线程，程序不会阻塞</span>
<span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#39;cost time:&#39;</span>,time<span style="color:#f92672">.</span>time() <span style="color:#f92672">-</span> start_time)
</code></pre></div><p><strong>6、GIL</strong> <strong>全局解释器锁：保证同一时间仅有一个线程对资源有操作权限</strong></p>
<p>**作用：**在一个进程内，同一时刻只能有一个线程执行</p>
<p>**说明：**python多线程中GIL锁只是在CPU操作时（如：计算）才是串行的，其他都是并行的，所以比串行快很多</p>
<p>​	1）为了解决不同线程同时访问同一资源时，数据保护问题，而产生了GIL</p>
<p>​	2）GIL在解释器的层面限制了程序在同一时间只有一个线程被CPU实际执行，而不管你的程序里实际开了多少条线程</p>
<p>​	3）为了解决这个问题，CPython自己定义了一个全局解释器锁，同一时间仅仅有一个线程可以拿到这个数据</p>
<p>​	4）python之所以会产生这种不好的状况是因为python启用一个线程是调用操作系统原生线程，就是C接口</p>
<p>​	5）但是这仅仅是CPython这个版本的问题，在PyPy，中就没有这种缺陷</p>
<p><strong>7.</strong> <strong>线程锁</strong></p>
<p>​	1）当一个线程对某个资源进行CPU计算的操作时加一个线程锁，只有当前线程计算完成主动释放锁，其他线程才能对其操作</p>
<p>​	2）这样就可以防止还未计算完成，释放GIL锁后其他线程对这个资源操作导致混乱问题</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#960050;background-color:#1e0010">用户锁使用举例</span>
<span style="color:#f92672">import</span> time
<span style="color:#f92672">import</span> threading
lock <span style="color:#f92672">=</span> threading<span style="color:#f92672">.</span>Lock()          <span style="color:#75715e">#1 生成全局锁</span>
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">addNum</span>():
    <span style="color:#66d9ef">global</span> num                  <span style="color:#75715e">#2 在每个线程中都获取这个全局变量</span>
    <span style="color:#66d9ef">print</span>(<span style="color:#e6db74">&#39;--get num:&#39;</span>,num )
    time<span style="color:#f92672">.</span>sleep(<span style="color:#ae81ff">1</span>)
    lock<span style="color:#f92672">.</span>acquire()              <span style="color:#75715e">#3 修改数据前加锁</span>
    num  <span style="color:#f92672">-=</span> <span style="color:#ae81ff">1</span>                   <span style="color:#75715e">#4 对此公共变量进行-1操作</span>
    lock<span style="color:#f92672">.</span>release()              <span style="color:#75715e">#5 修改后释放</span>
</code></pre></div><p><strong>8. Semaphore(</strong> <strong>信号量)</strong></p>
<ol>
<li>
<p>互斥锁 同时只允许一个线程更改数据，而Semaphore是同时允许一定数量的线程更改数据</p>
</li>
<li>
<p>比如厕所有3个坑，那最多只允许3个人上厕所，后面的人只能等里面有人出来了才能再进去</p>
</li>
<li>
<p>作用就是同一时刻允许运行的线程数量</p>
</li>
</ol>
<p><strong>9.</strong> <strong>线程池实现并发</strong></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> requests
<span style="color:#f92672">from</span> concurrent.futures <span style="color:#f92672">import</span> ThreadPoolExecutor
 
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">fetch_request</span>(url):
    result <span style="color:#f92672">=</span> requests<span style="color:#f92672">.</span>get(url)
    <span style="color:#66d9ef">print</span>(result<span style="color:#f92672">.</span>text)
 
url_list <span style="color:#f92672">=</span> [
    <span style="color:#e6db74">&#39;https://www.baidu.com&#39;</span>,
    <span style="color:#e6db74">&#39;https://www.google.com/&#39;</span>,         <span style="color:#75715e">#google页面会卡住，知道页面超时后这个进程才结束</span>
    <span style="color:#e6db74">&#39;http://dig.chouti.com/&#39;</span>,          <span style="color:#75715e">#chouti页面内容会直接返回，不会等待Google页面的返回</span>
]
 
pool <span style="color:#f92672">=</span> ThreadPoolExecutor(<span style="color:#ae81ff">10</span>)            <span style="color:#75715e"># 创建一个线程池，最多开10个线程</span>
<span style="color:#66d9ef">for</span> url <span style="color:#f92672">in</span> url_list:
    pool<span style="color:#f92672">.</span>submit(fetch_request,url)       <span style="color:#75715e"># 去线程池中获取一个线程，线程去执行fetch_request方法</span>
 
pool<span style="color:#f92672">.</span>shutdown(True)                      <span style="color:#75715e"># 主线程自己关闭，让子线程自己拿任务执行</span>
</code></pre></div><h2 id="17-协程">1.7 协程</h2>
<p><strong>1.</strong> <strong>什么是协程（进入上一次调用的状态）</strong></p>
<ol>
<li>
<p>协程，又称微线程，纤程，协程是一种用户态的轻量级线程。</p>
</li>
<li>
<p>线程的切换会保存到CPU的栈里，协程拥有自己的寄存器上下文和栈，</p>
</li>
<li>
<p>协程调度切换时，将寄存器上下文和栈保存到其他地方，在切回来的时候，恢复先前保存的寄存器上下文和栈</p>
</li>
<li>
<p>协程能保留上一次调用时的状态（即所有局部状态的一个特定组合），每次过程重入时，就相当于进入上一次调用的状态</p>
</li>
<li>
<p>协程最主要的作用是在单线程的条件下实现并发的效果，但实际上还是串行的（像yield一样）</p>
</li>
</ol>
<p><strong>2.</strong> <strong>协程缺点(无法利用多核资源)</strong></p>
<p>​	协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上线程阻塞（Blocking）操作（如IO时）会阻塞掉整个程序</p>
<p><strong>3.</strong> <strong>协程为何能处理大并发1：Greenlet遇到I/O手动切换</strong></p>
<ol>
<li>
<p>协程之所以快是因为遇到I/O操作就切换（最后只有CPU运算）</p>
</li>
<li>
<p>这里先演示用greenlet实现手动的对各个协程之间切换</p>
</li>
<li>
<p>其实Gevent模块仅仅是对greenlet的再封装，将I/O间的手动切换变成自动切换</p>
</li>
</ol>
<p><strong>4.</strong> <strong>协程为何能处理大并发2：Gevent遇到I/O自动切换</strong></p>
<ol>
<li>
<p>Gevent 是一个第三方库，可以轻松通过gevent实现并发同步或异步编程</p>
</li>
<li>
<p>在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程</p>
</li>
<li>
<p>Greenlet全部运行在主程序操作系统进程的内部，但它们被协作式地调度。</p>
</li>
<li>
<p>Gevent原理是只要遇到I/O操作就会自动切换到下一个协程</p>
</li>
</ol>
<p><strong>5.</strong> <strong>使用协程处理并发</strong></p>
<p><strong>注：</strong> <strong>Gevent只用起一个线程，当请求发出去后 gevent 就不管,永远就只有一个线程工作，谁先回来先处理</strong></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> gevent
<span style="color:#f92672">import</span> requests
<span style="color:#f92672">from</span> gevent <span style="color:#f92672">import</span> monkey
 
monkey<span style="color:#f92672">.</span>patch_all()
 
<span style="color:#75715e"># 这些请求谁先回来就先处理谁</span>
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">fetch_async</span>(method, url, req_kwargs):
    response <span style="color:#f92672">=</span> requests<span style="color:#f92672">.</span>request(method<span style="color:#f92672">=</span>method, url<span style="color:#f92672">=</span>url, <span style="color:#f92672">**</span>req_kwargs)
    <span style="color:#66d9ef">print</span>(response<span style="color:#f92672">.</span>url, response<span style="color:#f92672">.</span>content)
 
<span style="color:#75715e"># ##### 发送请求 #####</span>
gevent<span style="color:#f92672">.</span>joinall([
    gevent<span style="color:#f92672">.</span>spawn(fetch_async, method<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;get&#39;</span>, url<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;https://www.python.org/&#39;</span>, req_kwargs<span style="color:#f92672">=</span>{}),
    gevent<span style="color:#f92672">.</span>spawn(fetch_async, method<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;get&#39;</span>, url<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;https://www.google.com/&#39;</span>, req_kwargs<span style="color:#f92672">=</span>{}),
    gevent<span style="color:#f92672">.</span>spawn(fetch_async, method<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;get&#39;</span>, url<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;https://github.com/&#39;</span>, req_kwargs<span style="color:#f92672">=</span>{}),
])
</code></pre></div>
</div>


    </main>

    
  </body>
</html>
